package lineBasic

import (
	"context"
	"database/sql"
	"gf-demo/internal/dao"
	"gf-demo/internal/model"
	"gf-demo/internal/model/do"
	"gf-demo/internal/service"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
)

type (
	sLineBasic struct{}
)

func init() {
	service.RegisterLineBasic(New())
}

func New() service.ILineBasic {
	return &sLineBasic{}
}

func (s *sLineBasic) Create(ctx context.Context, in model.LineBasicCreateInput) (sql.Result, error) {
	//临时变量
	var (
		res       sql.Result //sql执行结果
		available bool       //查重LineCode和LineName
		createBy  int64      //创建人id（0-系统）
		err       error
	)
	//判断是注册还是新增用户
	isSignedIn := service.User().IsSignedIn(ctx)
	if isSignedIn {
		createBy = service.Session().GetUser(ctx).Id
	} else {
		createBy = 0
	}
	// LineCode checks.
	available, err = s.IsLineCodeAvailable(ctx, in.LineCode)
	if err != nil {
		return nil, err
	}
	if !available {
		column, _ := service.Locale().T(ctx, `table_lineBasic_lineCode`)
		str, _ := service.Locale().Tf(ctx, `used_column`, column, in.LineCode)
		return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, str)
	}
	// LineName checks.
	available, err = s.IsLineNameAvailable(ctx, in.LineName)
	if err != nil {
		return nil, err
	}
	if !available {
		column, _ := service.Locale().T(ctx, `table_lineBasic_lineName`)
		str, _ := service.Locale().Tf(ctx, `used_column`, column, in.LineName)
		return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, str)
	}
	id, errR := s.Count(ctx)
	if errR != nil {
		return nil, err
	}
	res, err = dao.DiAccLineBasic.Ctx(ctx).Data(do.DiAccLineBasic{
		Id:       id + 1,
		LineCode: in.LineCode,
		LineName: in.LineName,
		CreateBy: createBy,
	}).Insert()
	if err != nil {
		return nil, err
	}
	affectRows, err := res.RowsAffected()
	if err != nil {
		return nil, err
	}
	str, _ := service.Locale().Tf(ctx, `rows_affected`, affectRows)
	return res, gerror.NewCode(gcode.CodeOK, str)
}

func (s *sLineBasic) Delete(ctx context.Context, in model.LineBasicDeleteInput) (sql.Result, error) {
	var (
		res       sql.Result
		available bool
		err       error
	)
	// Id checks.
	available, err = s.IsIdAvailable(ctx, in.Id)
	if err != nil {
		return nil, err
	}
	if available {
		column, _ := service.Locale().T(ctx, `table_lineBasic_id`)
		str, _ := service.Locale().Tf(ctx, `not_exist_column_v_int`, column, in.Id)
		return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, str)
	}
	res, err = dao.DiAccLineBasic.Ctx(ctx).Delete("id", in.Id)
	if err != nil {
		return nil, err
	}
	affectRows, err := res.RowsAffected()
	if err != nil {
		return nil, err
	}
	str, _ := service.Locale().Tf(ctx, `rows_affected`, affectRows)
	return res, gerror.NewCode(gcode.CodeOK, str)
}

func (s *sLineBasic) Count(ctx context.Context) (int, error) {
	return dao.DiAccLineBasic.Ctx(ctx).Data(do.DiAccLineBasic{}).Count("id")
}

func (s *sLineBasic) Update(ctx context.Context, in model.LineBasicUpdateInput) (sql.Result, error) {
	//临时变量
	var (
		res       sql.Result
		err       error
		available bool  //id是否存在
		updateBy  int64 //修改人id
	)
	updateBy = service.Session().GetUser(ctx).Id
	// Id checks.
	available, err = s.IsIdAvailable(ctx, in.Id)
	if err != nil {
		return nil, err
	}
	if available {
		column, _ := service.Locale().T(ctx, `table_lineBasic_id`)
		str, _ := service.Locale().Tf(ctx, `not_exist_column_v_int`, column, in.Id)
		return nil, gerror.NewCode(gcode.CodeBusinessValidationFailed, str)
	}
	res, err = dao.DiAccLineBasic.Ctx(ctx).Data(do.DiAccLineBasic{
		LineCode: in.LineCode,
		LineName: in.LineName,
		UpdateBy: updateBy,
	}).Where(do.DiAccLineBasic{
		Id: in.Id,
	}).Update()
	if err != nil {
		return nil, err
	}
	affectRows, errR := res.RowsAffected()
	if errR != nil {
		return nil, err
	}
	str, _ := service.Locale().Tf(ctx, `rows_affected`, affectRows)
	return res, gerror.NewCode(gcode.CodeOK, str)
}

func (s *sLineBasic) GetList(ctx context.Context) (gdb.Result, error) {
	res, err := dao.DiAccLineBasic.Ctx(ctx).Data(do.DiAccLineBasic{}).All()
	if err != nil {
		return nil, err
	}
	str, _ := service.Locale().T(ctx, `request_success`)
	return res, gerror.NewCode(gcode.CodeOK, str)
}

func (s *sLineBasic) Get(ctx context.Context, in model.LineBasicGetInput) (gdb.Result, error) {
	if in.LineCode == "" && in.LineName == "" {
		return s.GetList(ctx)
	}
	res, err := dao.DiAccLineBasic.Ctx(ctx).
		Where("line_code", in.LineCode).
		WhereOrLike("line_name", in.LineName).
		All()
	if err != nil {
		return nil, err
	}
	str, _ := service.Locale().T(ctx, `request_success`)
	return res, gerror.NewCode(gcode.CodeOK, str)
}

// IsLineCodeAvailable checks and returns given lineCode is available for signing up.
func (s *sLineBasic) IsLineCodeAvailable(ctx context.Context, lineCode string) (bool, error) {
	count, err := dao.DiAccLineBasic.Ctx(ctx).Where(do.DiAccLineBasic{
		LineCode: lineCode,
	}).Count()
	if err != nil {
		return false, err
	}
	return count == 0, nil
}

// IsLineNameAvailable checks and returns given lineName is available for signing up.
func (s *sLineBasic) IsLineNameAvailable(ctx context.Context, lineName string) (bool, error) {
	count, err := dao.DiAccLineBasic.Ctx(ctx).Where(do.DiAccLineBasic{
		LineName: lineName,
	}).Count()
	if err != nil {
		return false, err
	}
	return count == 0, nil
}

// IsIdAvailable checks and returns given id is available.
func (s *sLineBasic) IsIdAvailable(ctx context.Context, id int) (bool, error) {
	count, err := dao.DiAccLineBasic.Ctx(ctx).Where(do.DiAccLineBasic{
		Id: id,
	}).Count()
	if err != nil {
		return false, err
	}
	return count == 0, nil
}
